home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Environments / PowerLisp 2.01 / PowerLisp 2.01 ƒ / Library / assembler_68k.lisp next >
Lisp/Scheme  |  1996-05-17  |  26KB  |  868 lines

  1. ;;;
  2. ;;;        PowerLisp 2.0
  3. ;;;        Copyright © 1996 Roger Corman.  All rights reserved.
  4. ;;;        68k Assembler source
  5. ;;;
  6.  
  7. ;
  8. ;    Source code for assembler.
  9. ;
  10.  
  11. ;
  12. ;    We do an eval-when on the entire file so that we get the
  13. ;    performance benefits immediately
  14. ;
  15. (eval-when (:compile-toplevel :load-toplevel :execute)
  16.     (provide :assembler)
  17.     (in-package :assembler))
  18.  
  19. (eval-when (:compile-toplevel :load-toplevel :execute)
  20. (export 
  21. '(
  22.      a0  a1  a2  a3  a4  a5  a6  a7
  23.     -a0 -a1 -a2 -a3 -a4 -a5 -a6 -a7
  24.      a0+ a1+ a2+ a3+ a4+ a5+ a6+ a7+
  25.      d0  d1  d2  d3  d4  d5  d6  d7
  26.     d-registers
  27.     a-registers
  28.     a-inc-registers
  29.     a-dec-registers
  30.     $CAR
  31.     $CDR
  32.     $SETCAR
  33.     $SETCDR
  34.     $SYMBOL-VALUE
  35.     $SYMBOL-PLIST
  36.     $NODE-TYPE
  37.     $CONSP
  38.     $INTEGER
  39.     $RETURN
  40.     $FUNC-BEGIN
  41.     $IF
  42.     $IFELSE
  43.     $REFERENCE
  44.     link
  45.     unlk
  46.     rts
  47.     dc.w
  48.     dc.l
  49.     moveq
  50.     move.l
  51.     move.b
  52.     move.w
  53.     movea.l
  54.     add.l
  55.     addi.l
  56.     and.l
  57.     andi.l
  58.     or.l
  59.     ori.l
  60.     eor.l
  61.     eori.l
  62.     sub.l
  63.     cmp.l
  64.     tst.l
  65.     subi.l
  66.     clr.l
  67.     lea
  68.     jsr
  69.     bra
  70.     bsr
  71.     bhi
  72.     bls
  73.     bcc
  74.     bcs
  75.     bne
  76.     beq
  77.     bvc
  78.     bvs
  79.     bpl
  80.     bmi
  81.     bge
  82.     blt
  83.     bgt
  84.     ble
  85.     movem.l
  86. )))
  87.  
  88. (defconstant a0 0)
  89. (defconstant a1 1)
  90. (defconstant a2 2)
  91. (defconstant a3 3)
  92. (defconstant a4 4)
  93. (defconstant a5 5)
  94. (defconstant a6 6)
  95. (defconstant a7 7)
  96.  
  97. (defconstant a0+ 0)
  98. (defconstant a1+ 1)
  99. (defconstant a2+ 2)
  100. (defconstant a3+ 3)
  101. (defconstant a4+ 4)
  102. (defconstant a5+ 5)
  103. (defconstant a6+ 6)
  104. (defconstant a7+ 7)
  105.  
  106. (defconstant -a0 0)
  107. (defconstant -a1 1)
  108. (defconstant -a2 2)
  109. (defconstant -a3 3)
  110. (defconstant -a4 4)
  111. (defconstant -a5 5)
  112. (defconstant -a6 6)
  113. (defconstant -a7 7)
  114.  
  115. (defconstant d0 0)
  116. (defconstant d1 1)
  117. (defconstant d2 2)
  118. (defconstant d3 3)
  119. (defconstant d4 4)
  120. (defconstant d5 5)
  121. (defconstant d6 6)
  122. (defconstant d7 7)
  123.  
  124. (defconstant d-registers '(d0 d1 d2 d3 d4 d5 d6 d7))
  125. (defconstant a-registers '(a0 a1 a2 a3 a4 a5 a6 a7))
  126. (defconstant a-inc-registers '(a0+ a1+ a2+ a3+ a4+ a5+ a6+ a7+))
  127. (defconstant a-dec-registers '(-a0 -a1 -a2 -a3 -a4 -a5 -a6 -a7))
  128.  
  129. ;;    Macros to access SYMBOL and NODE fields.
  130. ;;    These are dependent on the symbol class definition.
  131. ;;    The C++ source is in LispObjects.h.
  132.  
  133. (defconstant *symbol-value-offset*                 8)
  134. (defconstant *symbol-plist-offset*                 12)
  135. (defconstant *symbol-package-offset*             16)
  136. (defconstant *symbol-name-offset*                 20)
  137. (defconstant *symbol-flags-offset*                 24)
  138. (defconstant *symbol-jump-table-entry-offset*     26)
  139. (defconstant *symbol-jump-address-offset*         28)
  140. (defconstant *symbol-function-offset*             32)
  141.  
  142. (defconstant *node-car-offset*                    0)
  143. (defconstant *node-cdr-offset*                    4)
  144. (defconstant *node-flags-offset*                8)
  145. (defconstant *node-type-offset*                    9)
  146.  
  147. (defconstant *node-integer-offset*                0)    ;; occupies the car field
  148.  
  149. (defvar *assembler-address*    0)
  150. (defvar *assembler-local-address*    0)    ;; keep track of offset within instruction
  151. (defvar *assembler-references*    nil)
  152.  
  153. ;
  154. ;    We do an eval-when on the entire file so that we get the
  155. ;    performance benefits immediately
  156. ;
  157. (eval-when (:compile-toplevel :load-toplevel :execute)
  158.  
  159. (defmacro $CAR (areg &optional dest-reg)
  160.     (unless dest-reg (setq dest-reg areg))
  161.     `(
  162.         (move.l (,areg ,*node-car-offset*) ,dest-reg)
  163.      )) 
  164.  
  165. (defmacro $CDR (areg &optional dest-reg)
  166.     (unless dest-reg (setq dest-reg areg))
  167.     `(
  168.         (move.l (,areg ,*node-cdr-offset*) ,dest-reg)
  169.      )) 
  170.  
  171. (defmacro $SETCAR (areg value)
  172.     `(
  173.         (move.l ,value (,areg ,*node-car-offset*))
  174.      )) 
  175.  
  176. (defmacro $SETCDR (areg value)
  177.     `(
  178.         (move.l ,value (,areg ,*node-cdr-offset*))
  179.      )) 
  180.  
  181. (defmacro $SYMBOL-VALUE (areg)
  182.     `(
  183.         (move.l (,areg) ,areg)
  184.         (move.l (,areg ,*symbol-value-offset*) ,areg)
  185.         (move.l (,areg) ,areg)
  186.      )) 
  187.  
  188. (defmacro $SYMBOL-PLIST (areg)
  189.     `(
  190.         (move.l (,areg) ,areg)
  191.         (move.l (,areg ,*symbol-plist-offset*) ,areg)
  192.      )) 
  193.  
  194. ;; Extract the type field from a node
  195. (defmacro $NODE-TYPE (areg dest)
  196.     `(
  197.         (move.l (,areg ,(- *node-type-offset* 3)) ,dest)
  198.         (andi.l #x000000ff ,dest)
  199.     ))
  200.     
  201. (defmacro $CONSP (areg)
  202.     `(
  203.         ($NODE-TYPE ,areg d0)
  204.         (cmp.l 0 d0)
  205.     ))
  206.  
  207. (defmacro $INTEGER (areg &optional dest-reg)
  208.     (unless dest-reg (setq dest-reg areg))
  209.     `(
  210.         (move.l (,areg ,*node-integer-offset*) ,dest-reg)
  211.      )) 
  212.  
  213.     
  214. ;;
  215. ;;    The $RETURN macro zeros out the multiple value cell, stores
  216. ;;    the passed value in d0 (to return it), and unlinks the stack frame.
  217. ;;
  218. (defmacro $RETURN (retval)
  219.     (if (eq retval 'a0)
  220.         `(
  221.             (clr.l (common-lisp::%multiple-values-address))
  222.             (unlk a6)
  223.             (rts)
  224.          ) 
  225.         `(
  226.             (clr.l (common-lisp::%multiple-values-address))
  227.             (move.l ,retval a0)
  228.             (unlk a6)
  229.             (rts)
  230.          ))) 
  231.  
  232. ;;
  233. ;;    The $FUNC-BEGIN macro sets up the A6 stack frame link,
  234. ;;    and stores a pointer to the parameter block in A0.
  235. ;;    Usage:
  236. ;;        ($FUNC-BEGIN 4)        ;; allocates 4 bytes (space for one object)
  237. ;;                            ;; on the stack
  238. ;;
  239. (defmacro $FUNC-BEGIN (size)
  240.     `(
  241.         (link a6 ,size)
  242.         (move.l (a6 8) a0)
  243.      )) 
  244.  
  245. ;;
  246. ;;    $IF macro
  247. ;;    Usage:
  248. ;;        ($IF    
  249. ;;            (cmp.l d3 0)         ;; if d3 == 0 the next statement will be executed
  250. ;;            (
  251. ;;                (move.l d0 d3)
  252. ;;            ))
  253. ;;
  254. (defmacro $IF (condition instructions)
  255.     (let ((temp-label (gensym)))
  256.         ;;    allow single instruction clauses or lists of instructions
  257.         (if (not (listp (car condition)))
  258.             (setq condition (list condition)))
  259.         (if (not (listp (car instructions)))
  260.             (setq instructions (list instructions)))
  261.  
  262.         `(
  263.             ,@condition
  264.             (bne ,temp-label)
  265.             ,@instructions
  266.             ,temp-label
  267.          ))) 
  268.  
  269. ;;
  270. ;;    $IFELSE macro
  271. ;;    Usage:
  272. ;;        ($IFELSE    
  273. ;;            (cmp.l d3 0)         ;; if d3 == 0 the next instruction will be executed
  274. ;;            (
  275. ;;                (move.l d0 d3)
  276. ;;            )
  277. ;;            (
  278. ;;                (move.l d2 d3)    ;; otherwise this instruction will be executed
  279. ;;            ))
  280. ;;
  281. (defmacro $IFELSE (condition if-instructions else-instructions)
  282.     (let ((else-label (gensym)) 
  283.           (exit-label (gensym)))
  284.  
  285.         ;;    allow single instruction clauses or lists of instructions
  286.         (if (not (listp (car condition)))
  287.             (setq condition (list condition)))
  288.         (if (not (listp (car if-instructions)))
  289.             (setq if-instructions (list if-instructions)))
  290.         (if (not (listp (car else-instructions)))
  291.             (setq else-instructions (list else-instructions)))
  292.         
  293.         `(
  294.             ,@condition
  295.             (bne ,else-label)
  296.             ,@if-instructions
  297.             (bra ,exit-label)
  298.             ,else-label
  299.             ,@else-instructions
  300.             ,exit-label
  301.          ))) 
  302.  
  303. ;;
  304. ;;    The $REFERENCE macro does not generate any instructions, but
  305. ;;    is used by the compiler as a flag to the assembler to correctly
  306. ;;    generate address reference entries when code is compiled to a file.
  307. ;;
  308. (defmacro $REFERENCE (referenced-item)
  309.     nil)
  310.     
  311. (defmacro link (areg offset) `(,(+ (symbol-value areg) #x4e50) ,offset))
  312. (defmacro unlk (areg) `(,(+ (symbol-value areg) #x4e58)))
  313. (defmacro rts () `(#x4e75))
  314. (defmacro dc.w (w) 
  315.     (cond 
  316.         ((symbolp w) 
  317.          (add-reference `(%symbol-value-word ,w) -2)
  318.          (list (symbol-value w)))
  319.         (t (list w))))
  320.  
  321. (defmacro dc.l (w) 
  322.     (cond 
  323.         ((symbolp w) 
  324.          (add-reference `(%symbol-value ,w) -2)
  325.          (multiple-value-list (truncate (symbol-value w) #x10000)))
  326.         (t (multiple-value-list (truncate w #x10000)))))
  327.         
  328. (defmacro moveq (byte dreg)
  329.     (if (or (< byte 0) (> byte 255)) 
  330.         (error "Data out of range.~%Instruction: moveq  Value: ~A" byte))
  331.     (unless (member dreg d-registers) 
  332.         (error "Invalid data register. ~%Instruction: moveq  Operand: ~A" dreg))
  333.     (list (+ #x7000 byte (* (symbol-value dreg) #x200))))
  334.  
  335. (defmacro move.l (sreg dreg)
  336.     (move-instruction sreg dreg 'long))
  337.  
  338. (defmacro move.b (sreg dreg)
  339.     (move-instruction sreg dreg 'byte))
  340.  
  341. (defmacro move.w (sreg dreg)
  342.     (move-instruction sreg dreg 'word))
  343.  
  344. (defun move-instruction (sreg dreg size)
  345.     (let ((s (encode-address sreg size))(d (encode-address dreg size)) op-code)
  346.         (setq op-code 
  347.             (case size
  348.                 (long #x2000)
  349.                 (byte #x1000)
  350.                 (word #x3000)))
  351.         `(,(+ op-code 
  352.                 (* (encoded-address-reg d) #x200) ; destination register bits 9-11
  353.                 (* (encoded-address-mode d) #x40) ; destination mode bits 6-8
  354.                 (* (encoded-address-mode s) #x8)  ; source mode bits 3-5
  355.                 (encoded-address-reg s))          ; source register
  356.             ,@(encoded-address-data s)
  357.             ,@(encoded-address-data d))))
  358.         
  359.             
  360. (defmacro movea.l (sreg dreg)
  361.     (unless (member dreg a-registers) 
  362.         (error "Invalid address register. ~%Instruction: movea.l  Operand: ~A" dreg))
  363.     (let ((s (encode-address sreg))(d (symbol-value dreg)))
  364.         (append
  365.             (list (+ #x2040 
  366.                     (* d #x200)                ; destination register bits 9-11
  367.                     (* (encoded-address-mode s) #x8) ; source mode bits 3-5
  368.                     (encoded-address-reg s)))         ; source register
  369.             (encoded-address-data s))))
  370.  
  371. (defmacro add.l (src dest)
  372.     (let ((s (encode-address src))(d (encode-address dest)))
  373.         (unless (or (= (encoded-address-mode s) 0) 
  374.                     (= (encoded-address-mode d) 0))
  375.             (error 
  376.                 "The source or destination must be a d-register. ~%Instruction: add.l  Operands: ~A, ~A" src dest))
  377.         (if (= (encoded-address-mode s) 0)    ; if D-register is source
  378.             `(,(+ #xD000 
  379.                 (* (encoded-address-reg s) #x200)        ; source register bits 9-11
  380.                 (* 6 #x40)                                ; op-mode bits 6-8
  381.                 (* (encoded-address-mode d) #x8)        ; dest mode bits 3-5
  382.                 (encoded-address-reg d))                ; dest register
  383.                 ,@(encoded-address-data d))
  384.                                         ; else D-register is destination
  385.             `(,(+ #xD000 
  386.                 (* (encoded-address-reg d) #x200)        ; dest register bits 9-11
  387.                 (* 2 #x40)                                ; op-mode bits 6-8
  388.                 (* (encoded-address-mode s) #x8)        ; src mode bits 3-5
  389.                 (encoded-address-reg s))                ; src register
  390.                 ,@(encoded-address-data s)))))
  391.  
  392. (defmacro addi.l (src dest)
  393.     (incf *assembler-local-address* 4)
  394.     (let ((s src)(d (encode-address dest)))
  395.         (unless (integerp s)
  396.             (error "The source must be an integer. ~%Instruction: addi.l  Operand: ~A" s))
  397.         `(,(+ #x0680 
  398.                 (* (encoded-address-mode d) #x8)    ; dest mode bits 3-5
  399.                 (encoded-address-reg d))            ; dest register
  400.                 ,@(multiple-value-list (truncate s #x10000))
  401.                 ,@(encoded-address-data d))))
  402.  
  403. (defmacro and.l (src dest)
  404.     (let ((s (encode-address src))(d (encode-address dest)))
  405.         (unless (or (= (encoded-address-mode s) 0) 
  406.                     (= (encoded-address-mode d) 0))
  407.             (error 
  408.                 "The source or destination must be a d-register. ~%Instruction: and.l  Operands: ~A, ~A" src dest))
  409.         (if (or (= (encoded-address-mode s) 1) 
  410.                 (= (encoded-address-mode d) 1))
  411.             (error 
  412.                 "A-register not allowed as operand. ~%Instruction: and.l  Operands: ~A, ~A" src dest))
  413.         (if (= (encoded-address-mode s) 0); if D-register is source
  414.             `(,(+ #xC000 
  415.                 (* (encoded-address-reg s) #x200) ; source register bits 9-11
  416.                 (* 6 #x40)                        ; op-mode bits 6-8
  417.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  418.                 (encoded-address-reg d))        ; dest register
  419.                 ,@(encoded-address-data d))
  420.                                         ; else D-register is destination
  421.             `(,(+ #xC000 
  422.                 (* (encoded-address-reg d) #x200); dest register bits 9-11
  423.                 (* 2 #x40)                        ; op-mode bits 6-8
  424.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  425.                 (encoded-address-reg s))        ; src register
  426.                 ,@(encoded-address-data s)))))
  427.  
  428. (defmacro andi.l (src dest)
  429.     (incf *assembler-local-address* 4)
  430.     (let ((s src)(d (encode-address dest)))
  431.         (unless (integerp s)
  432.             (error "The source must be an integer. ~%Instruction: andi.l  Operand: ~A" src))
  433.         (if (= (encoded-address-mode d) 1)
  434.             (error "A-register not allowed as destination. ~%Instruction: andi.l  Operand: ~A" dest))
  435.         `(,(+ #x0280 
  436.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  437.                 (encoded-address-reg d))        ; dest register
  438.                 ,@(multiple-value-list (truncate s #x10000))
  439.                 ,@(encoded-address-data d))))
  440.  
  441. (defmacro or.l (src dest)
  442.     (let ((s (encode-address src))(d (encode-address dest)))
  443.         (unless (or (= (encoded-address-mode s) 0) 
  444.                     (= (encoded-address-mode d) 0))
  445.             (error 
  446.                 "The source or destination must be a d-register. ~%Instruction: or.l  Operands: ~A, ~A" src dest))
  447.         (if (or (= (encoded-address-mode s) 1) 
  448.                 (= (encoded-address-mode d) 1))
  449.             (error 
  450.                 "A-register not allowed as operand. ~%Instruction: or.l  Operands: ~A, ~A" src dest))
  451.         (if (= (encoded-address-mode s) 0)        ; if D-register is source
  452.             `(,(+ #x8000 
  453.                 (* (encoded-address-reg s) #x200); source register bits 9-11
  454.                 (* 6 #x40)                        ; op-mode bits 6-8
  455.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  456.                 (encoded-address-reg d))        ; dest register
  457.                 ,@(encoded-address-data d))
  458.                                         ; else D-register is destination
  459.             `(,(+ #x8000 
  460.                 (* (encoded-address-reg d) #x200); dest register bits 9-11
  461.                 (* 2 #x40)                        ; op-mode bits 6-8
  462.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  463.                 (encoded-address-reg s))        ; src register
  464.                 ,@(encoded-address-data s)))))
  465.  
  466. (defmacro ori.l (src dest)
  467.     (incf *assembler-local-address* 4)
  468.     (let ((s src)(d (encode-address dest)))
  469.         (unless (integerp s)
  470.             (error "The source of 'ori' must be an integer"))
  471.         (if (= (encoded-address-mode d) 1)
  472.             (error "ori: destination cannot be an a-register"))
  473.         `(,(+ #x0080 
  474.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  475.                 (encoded-address-reg d))        ; dest register
  476.                 ,@(multiple-value-list (truncate s #x10000))
  477.                 ,@(encoded-address-data d))))
  478.  
  479. (defmacro eor.l (src dest)
  480.     (let ((s (encode-address src))(d (encode-address dest)))
  481.         (unless (= (encoded-address-mode s) 0)
  482.             (error "eor: source must be a d-register"))
  483.         (if (= (encoded-address-mode d) 1)
  484.             (error "eor: destination cannot be an a-register"))
  485.         `(,(+ #xB000 
  486.             (* (encoded-address-reg s) #x200); source register bits 9-11
  487.             (* 6 #x40)                        ; op-mode bits 6-8
  488.             (* (encoded-address-mode d) #x8); dest mode bits 3-5
  489.             (encoded-address-reg d))        ; dest register
  490.             ,@(encoded-address-data d))))
  491.  
  492. (defmacro eori.l (src dest)
  493.     (incf *assembler-local-address* 4)
  494.     (let ((s src)(d (encode-address dest)))
  495.         (unless (integerp s)
  496.             (error "The source of 'eori' must be an integer"))
  497.         (if (= (encoded-address-mode d) 1)
  498.             (error "eor.i: destination cannot be an a-register"))
  499.         `(,(+ #x0A80 
  500.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  501.                 (encoded-address-reg d))        ; dest register
  502.                 ,@(multiple-value-list (truncate s #x10000))
  503.                 ,@(encoded-address-data d))))
  504.  
  505. (defmacro sub.l (src dest)
  506.     (let ((s (encode-address src))(d (encode-address dest)))
  507.         (unless (or (= (encoded-address-mode s) 0) 
  508.                     (= (encoded-address-mode d) 0))
  509.             (error "The source or destination of 'sub' must be a d-register"))
  510.         (if (= (encoded-address-mode s) 0)        ; if D-register is source
  511.             `(,(+ #x9000 
  512.                 (* (encoded-address-reg s) #x200); source register bits 9-11
  513.                 (* 6 #x40)                        ; op-mode bits 6-8
  514.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  515.                 (encoded-address-reg d))        ; dest register
  516.                 ,@(encoded-address-data d))
  517.                                         ; else D-register is destination
  518.             `(,(+ #x9000 
  519.                 (* (encoded-address-reg d) #x200); dest register bits 9-11
  520.                 (* 2 #x40)                        ; op-mode bits 6-8
  521.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  522.                 (encoded-address-reg s))        ; src register
  523.                 ,@(encoded-address-data s)))))
  524.  
  525. (defmacro cmp.l (src dest)
  526.     (let ((s (encode-address src))(d (encode-address dest)))
  527.         (unless (= (encoded-address-mode d) 0)
  528.             (error "The destination of 'cmp' must be a d-register"))
  529.         `(,(+ #xb000 
  530.             (* (encoded-address-reg d) #x200); dest register bits 9-11
  531.             (* 2 #x40)                        ; op-mode bits 6-8
  532.             (* (encoded-address-mode s) #x8); src mode bits 3-5
  533.             (encoded-address-reg s))        ; src register
  534.             ,@(encoded-address-data s))))
  535.  
  536. (defmacro tst.l (dest)
  537.     (let ((d (encode-address dest)))
  538.         `(,(+ #x4A00
  539.                 (* #x40 2)                        ; size = long
  540.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  541.                 (encoded-address-reg d))        ; dest register
  542.                 ,@(encoded-address-data d))))
  543.  
  544. (defmacro subi.l (src dest)
  545.     (incf *assembler-local-address* 4)
  546.     (let ((s src)(d (encode-address dest)))
  547.         (unless (integerp s)
  548.             (error "The source of 'subi' must be an integer"))
  549.         `(,(+ #x0480 
  550.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  551.                 (encoded-address-reg d))        ; dest register
  552.                 ,@(multiple-value-list (truncate s #x10000))
  553.                 ,@(encoded-address-data d))))
  554.  
  555. (defmacro clr.l (dest)
  556.     (let ((d (encode-address dest)))
  557.         `(,(+ #x4200
  558.                 (* #x40 2)                        ; size = long
  559.                 (* (encoded-address-mode d) #x8); dest mode bits 3-5
  560.                 (encoded-address-reg d))        ; dest register
  561.                 ,@(encoded-address-data d))))
  562.  
  563. (defmacro lea (src dest)
  564.     (let ((s (encode-address src))(d (encode-address dest)))
  565.         (unless (= (encoded-address-mode d) 1)
  566.             (error "The destination of 'lea' must be an a-register"))
  567.         `(,(+ #x41C0
  568.                 (* #x200 (encoded-address-reg d)); dest register bits 9-11
  569.                 (* (encoded-address-mode s) #x8); src mode bits 3-5
  570.                 (encoded-address-reg s))        ; src register
  571.                 ,@(encoded-address-data s))))
  572.  
  573. (defmacro jsr (dst)
  574.  
  575.     (if (symbolp dst) 
  576.         (progn
  577.             (add-reference `(symbol-value ,dst))
  578.             (setq dst (symbol-value dst))))
  579.             
  580.     (if (consp dst)
  581.         (if (eq (car dst) 'function)
  582.             (progn
  583.                 (add-reference dst)
  584.                 (return (cons #x4eb9 
  585.                     (multiple-value-list 
  586.                         (truncate (exec-address (cadr dst)) #x10000))))))
  587.         ;; else
  588.         (error "Invalid destination.~%Instruction: jsr  Destination: ~A" dst))
  589.         
  590.     (let ((d (encode-address dst)))
  591.         (append
  592.             (list (+ #x4e80
  593.                     (* (encoded-address-mode d) #x8); dest mode bits 3-5
  594.                     (encoded-address-reg d)))        ; dest register
  595.             (encoded-address-data d))))
  596.  
  597. (defmacro bra (dest) `(#x6000 ,dest))
  598. (defmacro bsr (dest) `(#x6100 ,dest))
  599. (defmacro bhi (dest) `(#x6200 ,dest))
  600. (defmacro bls (dest) `(#x6300 ,dest))
  601. (defmacro bcc (dest) `(#x6400 ,dest))
  602. (defmacro bcs (dest) `(#x6500 ,dest))
  603. (defmacro bne (dest) `(#x6600 ,dest))
  604. (defmacro beq (dest) `(#x6700 ,dest))
  605. (defmacro bvc (dest) `(#x6800 ,dest))
  606. (defmacro bvs (dest) `(#x6900 ,dest))
  607. (defmacro bpl (dest) `(#x6a00 ,dest))
  608. (defmacro bmi (dest) `(#x6b00 ,dest))
  609. (defmacro bge (dest) `(#x6c00 ,dest))
  610. (defmacro blt (dest) `(#x6d00 ,dest))
  611. (defmacro bgt (dest) `(#x6e00 ,dest))
  612. (defmacro ble (dest) `(#x6f00 ,dest))
  613.     
  614. (setf (get 'd0 'post-increment-mask) #x0001)
  615. (setf (get 'd1 'post-increment-mask) #x0002)
  616. (setf (get 'd2 'post-increment-mask) #x0004)
  617. (setf (get 'd3 'post-increment-mask) #x0008)
  618. (setf (get 'd4 'post-increment-mask) #x0010)
  619. (setf (get 'd5 'post-increment-mask) #x0020)
  620. (setf (get 'd6 'post-increment-mask) #x0040)
  621. (setf (get 'd7 'post-increment-mask) #x0080)
  622. (setf (get 'a0 'post-increment-mask) #x0100)
  623. (setf (get 'a1 'post-increment-mask) #x0200)
  624. (setf (get 'a2 'post-increment-mask) #x0400)
  625. (setf (get 'a3 'post-increment-mask) #x0800)
  626. (setf (get 'a4 'post-increment-mask) #x1000)
  627. (setf (get 'a5 'post-increment-mask) #x2000)
  628. (setf (get 'a6 'post-increment-mask) #x4000)
  629. (setf (get 'a7 'post-increment-mask) #x8000)
  630.  
  631. (setf (get 'a7 'pre-decrement-mask) #x0001)
  632. (setf (get 'a6 'pre-decrement-mask) #x0002)
  633. (setf (get 'a5 'pre-decrement-mask) #x0004)
  634. (setf (get 'a4 'pre-decrement-mask) #x0008)
  635. (setf (get 'a3 'pre-decrement-mask) #x0010)
  636. (setf (get 'a2 'pre-decrement-mask) #x0020)
  637. (setf (get 'a1 'pre-decrement-mask) #x0040)
  638. (setf (get 'a0 'pre-decrement-mask) #x0080)
  639. (setf (get 'd7 'pre-decrement-mask) #x0100)
  640. (setf (get 'd6 'pre-decrement-mask) #x0200)
  641. (setf (get 'd5 'pre-decrement-mask) #x0400)
  642. (setf (get 'd4 'pre-decrement-mask) #x0800)
  643. (setf (get 'd3 'pre-decrement-mask) #x1000)
  644. (setf (get 'd2 'pre-decrement-mask) #x2000)
  645. (setf (get 'd1 'pre-decrement-mask) #x4000)
  646. (setf (get 'd0 'pre-decrement-mask) #x8000)
  647.  
  648. (defmacro movem.l (&rest r)
  649.     (incf *assembler-local-address* 2)
  650.     (let ((instruction 0) (mask 0) (ea))
  651.     (if (consp (car r))        ;; post-increment-mode
  652.         (progn
  653.             (setq ea (encode-address (car r)))
  654.             (setq r (cdr r))
  655.             (setq instruction 
  656.                 (+ #x4cc0 
  657.                     (* (encoded-address-mode ea) 8) 
  658.                     (encoded-address-reg ea)))
  659.             (dolist (i r) (setq mask (+ mask (get i 'post-increment-mask))))
  660.             (return (list* instruction mask (encoded-address-data ea)))) 
  661.         (progn                ;; else pre-decrement-mode
  662.             (setq ea (encode-address (car (last r))))
  663.             (setq instruction 
  664.                 (+ #x48c0 
  665.                     (* (encoded-address-mode ea) 8) 
  666.                     (encoded-address-reg ea)))
  667.             (dolist (i r) 
  668.                 (if (symbolp i)
  669.                     (setq mask (+ mask (get i 'pre-decrement-mask)))))
  670.             (return (list* instruction mask (encoded-address-data ea))))))) 
  671.  
  672. (defun long-words (addr) (multiple-value-list (floor addr #x10000)))
  673.  
  674. ;
  675. ;    encode-address
  676. ;    Returns a list consisting of:
  677. ;        (mode reg data1 data2 data3 ...)
  678. ;    where there may be [0..n] data words (16-bit quantities)
  679. ;
  680. (defun encode-address (addr &optional (size 'long) &aux retval) 
  681.     (cond
  682.         ((and (consp addr) (eq (car addr) 'function))
  683.          (let ((exec (exec-address (cadr addr))))
  684.             (add-reference addr)
  685.             (setq retval (list* 7 4 (long-words exec)))))
  686.  
  687.         ((and (consp addr) (eq (car addr) 'quote))
  688.          (let ((exec (address (cadr addr))))
  689.             (add-reference addr)
  690.             (setq retval (list* 7 4 (long-words exec)))))
  691.  
  692.         ((and (consp addr) (eq (car addr) 'symbol-function))
  693.          (let ((func (address (symbol-function (cadr addr)))))
  694.             (add-reference addr)
  695.             (setq retval (list* 7 4 (long-words func)))))
  696.  
  697.         ((symbolp addr)
  698.          (cond
  699.             ((member addr d-registers) 
  700.                 (setq retval (list 0 (symbol-value addr))))
  701.             ((member addr a-registers) 
  702.                 (setq retval (list 1 (symbol-value addr))))
  703.             (t 
  704.                 (add-reference `(symbol-value ,addr))
  705.                 (setq addr (symbol-value addr))
  706.                 (if (eq size 'long)
  707.                     (setq retval (list* 7 4 (long-words addr)))
  708.                     (setq retval (list 7 4 (mod addr #x10000)))))))
  709.  
  710.         ((consp addr)
  711.          (setq retval 
  712.             (cond
  713.                 ((member (car addr) a-registers) 
  714.                  (if (and (cdr addr) (/= (cadr addr) 0))
  715.                      (list* 5 (symbol-value (car addr)) (cdr addr))
  716.                     (list 2 (symbol-value (car addr)))))
  717.                 ((member (car addr) a-inc-registers) 
  718.                  (list 3 (symbol-value (car addr))))
  719.                 ((member (car addr) a-dec-registers) 
  720.                  (list 4 (symbol-value (car addr))))
  721.                 ((and (symbolp (car addr)) (null (cdr addr)))
  722.                  (add-reference `(symbol-value ,(car addr)))
  723.                  (list* 7 1 (long-words (symbol-value (car addr)))))
  724.                 ((and (integerp (car addr)) (null (cdr addr)))
  725.                  (list* 7 1 (long-words (car addr))))
  726.                 (t (error "Unknown address expression: ~A" addr)))))
  727.  
  728.         ((integerp addr)
  729.          (if (eq size 'long)
  730.             (setq retval (list* 7 4 (long-words addr)))
  731.             (setq retval (list 7 4 (mod addr #x10000)))))
  732.             
  733.         (t (error "Unknown address expression: ~A" addr)))
  734.  
  735.     (if (> (length retval) 2)
  736.         (incf *assembler-local-address* (* 2 (length retval))))
  737.     (return retval))
  738.  
  739. ;;
  740. ;;    encoded-address-mode
  741. ;;    Returns the mode (integer) of the passed address structure.
  742. ;;
  743. (defun encoded-address-mode (addr)
  744.     (car addr))
  745.  
  746. (defun encoded-address-reg (addr)
  747.     (cadr addr))
  748.  
  749. (defun encoded-address-data (addr)
  750.     (cddr addr))
  751.     
  752. (defun assemble (assembler-instructions references &optional environment)
  753.   (let*
  754.     ((label-table (make-hash-table :test #'eql))
  755.       (newlist nil)
  756.       (codelist nil)
  757.       (*assembler-address* 0)
  758.       (*assembler-local-address* 0)
  759.       (*assembler-references* nil)
  760.       operator)
  761.  
  762.     (do ((n assembler-instructions (cdr n))
  763.          statement)
  764.         ((null n))
  765.         (setq statement (car n))
  766.         (cond
  767.             ;; if it is a label, add it to the hash table
  768.             ((symbolp statement) 
  769.              (setf (gethash statement label-table) *assembler-address*))
  770.             ((consp statement)
  771.              (if (integerp (car statement))     ;; skip address if there is one
  772.                  (setq statement (cdr statement)))
  773.              
  774.              ;; make sure there is a macro definition
  775.              (setq operator (car statement))
  776.              (unless (symbolp operator) 
  777.                  (error "Invalid instruction: ~A" operator))
  778.              (unless (macro-function operator)
  779.                  (error "No definition for instruction: ~A" statement))
  780.  
  781.              ;; expand the macro one time
  782.              (setq *assembler-local-address* 2)    ;; reset this each instruction
  783.              (setq statement (macroexpand-1 statement))
  784.              
  785.              ;; check for multiple statement result (assembler macro expansion)
  786.              (if (and (consp statement) (not (integerp (car statement))))
  787.                  ;; just splice in the new instructions and continue
  788.                 (setq n (append (list nil) statement (cdr n)))
  789.                 (if (consp statement)
  790.                     ;; This address is only correct because we are requiring
  791.                     ;; all branch destinations to be 16-bit offsets. 
  792.                     ;; This avoids having to calculate the sizes here.
  793.                     ;; i.e. each symbol becomes one 16-bit displacement word.
  794.                     (progn
  795.                         (incf *assembler-address* (* (length statement) 2))
  796.                         (push statement newlist)))))
  797.             
  798.             ;; error if not a symbol or a list
  799.             (t (error "Invalid label encountered: ~A" statement))))
  800.             
  801.     ;; Now go through and append all the sublists together,
  802.     ;; resolving branch addresses as we go.
  803.     ;; We only currently support 16-bit displacements in the branch
  804.     ;; instructions.
  805.  
  806.     (setq newlist (reverse newlist))
  807.     (setq *assembler-address* 0)
  808.     (dolist (statement newlist)
  809.         
  810.         ;; check for branch instructions
  811.         (setq operator (car statement))
  812.         (if (= (truncate operator #x1000) 6)
  813.             (if (and (consp (cdr statement))
  814.                     (symbolp (cadr statement)))
  815.                 (let* ((sym (cadr statement))
  816.                         (value (gethash sym label-table)))
  817.                     (unless value 
  818.                         (error "Label not found: ~A" sym))
  819.                     (unless (integerp value) 
  820.                         (error "Invalid label found.~%~ALabel: ~A Value: ~A" sym value))
  821.                     (setf (cadr statement) (- value (+ *assembler-address* 2))))))
  822.         
  823.         (incf *assembler-address* (* 2 (length statement)))
  824.         (dolist (n statement) (push n codelist)))
  825.         
  826.     (%build-function (reverse codelist) (nreverse *assembler-references*) environment)))
  827.  
  828. (defun add-reference (ref &optional (offset 0))
  829.     (push 
  830.         (cons ref (+ *assembler-address* *assembler-local-address* offset)) 
  831.         *assembler-references*))
  832.  
  833. )  ;; close enclosing eval-when form
  834.     
  835. ;;    add defasm to the common lisp package
  836.  
  837. (eval-when (:compile-toplevel :load-toplevel :execute)
  838.     (in-package :common-lisp)
  839.     (export 'common-lisp::defasm))
  840.  
  841. (eval-when (:compile-toplevel :load-toplevel :execute)
  842. (defmacro defasm (name lambda-list &rest forms)
  843. ;    (declare (unused lambda-list))
  844.     (let ((doc-form nil))
  845.         (if (and (typep (car forms) 'string)
  846.                 (cdr forms))
  847.             (progn
  848.                 (setq doc-form 
  849.                     `((setf (documentation ',name 'function) ,(car forms))))
  850.                 (setq forms (cdr forms))))
  851.  
  852.         `(progn
  853.             ,@doc-form
  854.             (setf (symbol-function ',name) ,(car forms))
  855.             (null-environment (function ,name))
  856.             ',name))) 
  857. ) ;; close eval-when
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867.  
  868.